#ifndef AVALON_SERVICEPROTOCOLSERVLET_HPP
#define AVALON_SERVICEPROTOCOLSERVLET_HPP
#include "Avalon/Services/ServiceProtocolServletContainer.hpp"

namespace Avalon {
namespace Services {

  /*! \class ServiceProtocolServlet
      \brief Base class for a servlet.
      \tparam ServletType The servlet's type.
      \tparam ChannelType The type of Channel the servlet responds to.
   */
  template<typename ServletType, typename ChannelType>
  class ServiceProtocolServlet {
    public:

      //! Constructs a ServiceProtocolServlet.
      ServiceProtocolServlet();

      ~ServiceProtocolServlet();

    protected:

      //! Sets the request handler for a service.
      /*!
        \tparam Service The Service being handled.
        \param slot The slot called to handle the <i>Service</i>.
      */
      template<typename Service>
      void SetHandler(const typename Service::Request::Slot& slot);

      //! Sends a Message to a Channel.
      /*!
        \param channel The Channel to send the Message to.
        \param message The Message to send.
      */
      void SendMessage(ChannelType* channel, const Message& message);

      //! Sends a Message to a list of Channels.
      /*!
        \param channels The Channels to send the Message to.
        \param message The Message to send.
      */
      void SendMessage(const std::vector<ChannelType*>& channels,
        const Message& message);

    private:
      friend class ServiceProtocolServletContainer<ServletType, ChannelType>;
      ServiceProtocolServletContainer<ServletType, ChannelType>* m_container;

      void SetContainer(ServiceProtocolServletContainer<
        ServletType, ChannelType>* container);
  };

  template<typename ServletType, typename ChannelType>
  ServiceProtocolServlet<ServletType, ChannelType>::ServiceProtocolServlet() {}

  template<typename ServletType, typename ChannelType>
  ServiceProtocolServlet<ServletType, ChannelType>::~ServiceProtocolServlet() {}

  template<typename ServletType, typename ChannelType>
  template<typename Service>
  void ServiceProtocolServlet<ServletType, ChannelType>::SetHandler(
      const typename Service::Request::Slot& slot) {
    m_container->SetHandler<Service>(slot);
  }

  template<typename ServletType, typename ChannelType>
  void ServiceProtocolServlet<ServletType, ChannelType>::SendMessage(
      ChannelType* channel, const Message& message) {
    m_container->SendMessage(channel, message);
  }

  template<typename ServletType, typename ChannelType>
  void ServiceProtocolServlet<ServletType, ChannelType>::SendMessage(
      const std::vector<ChannelType*>& channels, const Message& message) {
    m_container->SendMessage(channels, message);
  }

  template<typename ServletType, typename ChannelType>
  void ServiceProtocolServlet<ServletType, ChannelType>::SetContainer(
      ServiceProtocolServletContainer<ServletType, ChannelType>* container) {
    m_container = container;
  }
}
}

#endif // AVALON_SERVICEPROTOCOLSERVLET_HPP
